﻿namespace Movies.ViewModel
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.IO;
    using System.Linq;
    using System.Threading;
    using System.Windows.Forms;
    using System.Windows.Input;
    using Movies.Commands;
    using Movies.Helpers;
    using MoviesDataBase;

    /// <summary>
    /// Le viewmodel.
    /// </summary>
    public class ViewModel : INotifyPropertyChanged
    {
        #region Attributes
        /// <summary>
        /// The list of the movies.
        /// </summary>
        private List<CoverViewModel> movies;

        /// <summary>
        /// The selected movie.
        /// </summary>
        private CoverViewModel selectedMovie;

        /// <summary>
        /// The selected directory.
        /// </summary>
        private string selectedDirectory;
        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="ViewModel"/> class.
        /// </summary>
        public ViewModel()
        {
            this.ScanDirectory = new RelayCommand(new Action<object>((e) => this.SelectDirectoryToScan()));
            this.RefreshSelectedMovie = new RelayCommand(new Action<object>(this.UpdateSelectedMovie));
            this.ExportPdfCommand = new RelayCommand(new Action<object>((e) => this.ExportPdfMovies()));
            this.ExportWordCommand = new RelayCommand(new Action<object>((e) => this.ExportWordMovies()));
            this.ExportXmlCommand = new RelayCommand(new Action<object>((e) => this.ExportXmlMovies()));
            this.ExportTextCommand = new RelayCommand(new Action<object>((e) => this.ExportTextMovies()));

            foreach (var movie in DataProvider.Instance.GetMovies())
            {
                this.Movies.Add(new CoverViewModel(movie.Title, movie.Path));
            }
        }

        #endregion

        #region Events

        /// <summary>
        /// Se produit lorsqu'une valeur de propriété est modifiée.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the selected directory.
        /// </summary>
        /// <value>
        /// The selected directory.
        /// </value>
        public string SelectedDirectory
        {
            get
            {
                return this.selectedDirectory;
            }

            set
            {
                this.selectedDirectory = value;
                this.NotifyPropertyChanged("SelectedDirectory");
                this.Scan(this.selectedDirectory);
            }
        }

        /// <summary>
        /// Gets or sets the selected movie.
        /// </summary>
        /// <value>
        /// The selected movie.
        /// </value>
        public CoverViewModel SelectedMovie
        {
            get
            {
                return this.selectedMovie;
            }

            set
            {
                this.selectedMovie = value;
                this.NotifyPropertyChanged("SelectedMovie");
            }
        }
        #endregion

        #region Commands
        /// <summary>
        /// Gets or sets the scan directory.
        /// </summary>
        /// <value>
        /// The scan directory.
        /// </value>
        public ICommand ScanDirectory { get; set; }

        /// <summary>
        /// Gets or sets the export text command.
        /// </summary>
        /// <value>
        /// The export text command.
        /// </value>
        public ICommand ExportTextCommand { get; set; }

        /// <summary>
        /// Gets or sets the export movie command.
        /// </summary>
        /// <value>
        /// The export movie command.
        /// </value>
        public ICommand ExportPdfCommand { get; set; }

        /// <summary>
        /// Gets or sets the export movie command.
        /// </summary>
        /// <value>
        /// The export movie command.
        /// </value>
        public ICommand ExportWordCommand { get; set; }

        /// <summary>
        /// Gets or sets the export XML command.
        /// </summary>
        /// <value>
        /// The export XML command.
        /// </value>
        public ICommand ExportXmlCommand { get; set; }

        /// <summary>
        /// Gets or sets the refresh selected movie.
        /// </summary>
        /// <value>
        /// The refresh selected movie.
        /// </value>
        public ICommand RefreshSelectedMovie { get; set; }

        #endregion

        #region Methods
        /// <summary>
        /// Gets the movies.
        /// </summary>
        public System.Collections.ObjectModel.ObservableCollection<CoverViewModel> Movies
        {
            get
            {
                if (this.movies == null)
                {
                    this.movies = new List<CoverViewModel>();
                    foreach (Movie m in DataProvider.Instance.Entities.Movies)
                    {
                        movies.Add(new CoverViewModel(m));
                    }
#if DEBUG
                    ////this.Scan(ConfigurationManager.AppSettings["RootDirectory"]);
#endif
                }

                return new System.Collections.ObjectModel.ObservableCollection<CoverViewModel>(this.movies);
            }
        }

        /// <summary>
        /// Scans the specified root.
        /// </summary>
        /// <param name="root">The root.</param>
        private void Scan(string root)
        {
            foreach (string dir in Directory.GetDirectories(root))
            {
                this.Scan(dir);
            }

            foreach (string f in Directory.GetFiles(root))
            {
                FileInfo fi = new FileInfo(f);
                string title;
                if (!string.IsNullOrEmpty(fi.Extension))
                {
                    title = fi.Name.Replace(fi.Extension, string.Empty);
                }
                else
                {
                    title = fi.Name;
                }

                CoverViewModel cvm = new CoverViewModel(title, f);

                this.movies.Add(cvm);
            }

            this.NotifyPropertyChanged("Movies");
        }

        /// <summary>
        /// Selects the directory to scan.
        /// </summary>
        private void SelectDirectoryToScan()
        {
            System.Windows.Forms.FolderBrowserDialog ofd = new System.Windows.Forms.FolderBrowserDialog();
            if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                this.SelectedDirectory = ofd.SelectedPath;
            }
        }

        /// <summary>
        /// Updates the selected movie.
        /// </summary>
        /// <param name="o">The o.</param>
        private void UpdateSelectedMovie(object o)
        {
            if (this.SelectedMovie != null)
            {
                ThreadStart ts = new ThreadStart(() => this.SelectedMovie.AllocineParser.DownloadMovieInformationAsync());
                new Thread(ts).Start();
            }
        }

        /// <summary>
        /// Exports the movies.
        /// </summary>
        private void ExportTextMovies()
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.AddExtension = true;
            sfd.Filter = "Fichiers text | *.txt";
            sfd.DefaultExt = "txt";

            DialogResult result = sfd.ShowDialog();

            if (!string.IsNullOrEmpty(sfd.FileName))
            {
                MovieExporter.ExportMovie(sfd.FileName, this.movies.Select(m => m.Movie), Exporter.Format.TXT);
            }
        }

        /// <summary>
        /// Exports the movies.
        /// </summary>
        private void ExportPdfMovies()
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.AddExtension = true;
            sfd.Filter = "Fichiers pdf | *.pdf";
            sfd.DefaultExt = "pdf";

            DialogResult result = sfd.ShowDialog();

            if (!string.IsNullOrEmpty(sfd.FileName))
            {
                MovieExporter.ExportMovie(sfd.FileName, this.movies.Select(m => m.Movie), Exporter.Format.PDF);
            }
        }

        /// <summary>
        /// Exports the movies.
        /// </summary>
        private void ExportWordMovies()
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.AddExtension = true;
            sfd.Filter = "Fichiers word | *.docx";
            sfd.DefaultExt = "docx";

            DialogResult result = sfd.ShowDialog();

            if (!string.IsNullOrEmpty(sfd.FileName))
            {
                MovieExporter.ExportMovie(sfd.FileName, this.movies.Select(m => m.Movie), Exporter.Format.Doc);
            }
        }

        /// <summary>
        /// Exports the XML movies.
        /// </summary>
        private void ExportXmlMovies()
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.AddExtension = true;
            sfd.Filter = "Fichiers xml | *.xml";
            sfd.DefaultExt = "xml";

            DialogResult result = sfd.ShowDialog();

            if (!string.IsNullOrEmpty(sfd.FileName))
            {
                MovieExporter.ExportMovie(sfd.FileName, this.movies.Select(m => m.Movie), Exporter.Format.XML);
            }
        }

        /// <summary>
        /// Notifies the property changed.
        /// </summary>
        /// <param name="info">The info.</param>
        private void NotifyPropertyChanged(string info)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }

        #endregion
    }
}
